﻿#region Using directives

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
//using System.ComponentModel.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Windows.Forms;

#endregion

namespace NCS_CS
{

    public class SortableBindingList<T> : BindingList<T>
    {

        #region Sorting

        private bool _isSorted;

        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
        {

            // Get list to sort
            List<T> items = this.Items as List<T>;

            // Apply and set the sort, if items to sort
            if (items != null)
            {
                PropertyComparer<T> pc = new PropertyComparer<T>(property, direction);
                items.Sort(pc);
                _isSorted = true;
            }
            else
            {
                _isSorted = false;
            }

            // Let bound controls know they should refresh their views
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        protected override bool IsSortedCore
        {
            get { return _isSorted; }
        }

        protected override void RemoveSortCore()
        {
            _isSorted = false;
        }

        #endregion

        #region Persistence

        // NOTE: BindingList<T> is not serializable but List<T> is

        //public void Save(string filename)
        //{
        //    BinaryFormatter formatter = new BinaryFormatter();
        //    using (FileStream stream = new FileStream(filename, FileMode.Create))
        //    {
        //        // Serialize data list items
        //        formatter.Serialize(stream, (List<T>)this.Items);
        //    }
        //}

        //public void Load(string filename)
        //{

        //    this.ClearItems();

        //    if (File.Exists(filename))
        //    {
        //        BinaryFormatter formatter = new BinaryFormatter();
        //        using (FileStream stream = new FileStream(filename, FileMode.Open))
        //        {
        //            // Deserialize data list items
        //            ((List<T>)this.Items).AddRange((IEnumerable<T>)formatter.Deserialize(stream));
        //        }
        //    }

        //    // Let bound controls know they should refresh their views
        //    this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        //}

        #endregion
    }
    public class SortableBindingList2<T> : System.ComponentModel.BindingList<T>
    {
        // constructor
        public SortableBindingList2(System.Collections.Generic.List<T> list)
            : base(list) 
        { 
        }
        public SortableBindingList2()
        {

        }
        // fields
        private bool m_IsSorted;
        private System.ComponentModel.ListSortDirection m_SortDirection;
        private System.ComponentModel.PropertyDescriptor m_SortProperty;

        // properties
        protected override System.ComponentModel.ListSortDirection SortDirectionCore { get { return m_SortDirection; } }
        protected override System.ComponentModel.PropertyDescriptor SortPropertyCore { get { return m_SortProperty; } }
        protected override bool IsSortedCore { get { return m_IsSorted; } }
        protected override bool SupportsSortingCore { get { return true; } }

        // methods
        protected override void RemoveSortCore() { m_IsSorted = false; }
        protected override void ApplySortCore(System.ComponentModel.PropertyDescriptor prop, System.ComponentModel.ListSortDirection direction)
        {
            if (prop.PropertyType.GetInterface("IComparable") == null)
                return;
            var _List = this.Items as System.Collections.Generic.List<T>;
            if (_List == null)
            {
                m_IsSorted = false;
            }
            else
            {
                var _Comparer = new PropertyComparer(prop.Name, direction);
                _List.Sort(_Comparer);
                m_IsSorted = true;
                m_SortDirection = direction;
                m_SortProperty = prop;
            }
            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, -1));
        }

        // sub class
        public class PropertyComparer : System.Collections.Generic.IComparer<T>
        {
            // properties
            private System.Reflection.PropertyInfo PropInfo { get; set; }
            private System.ComponentModel.ListSortDirection Direction { get; set; }

            // methods
            public PropertyComparer(string propName, System.ComponentModel.ListSortDirection direction)
            {
                this.PropInfo = typeof(T).GetProperty(propName);
                this.Direction = direction;
            }
            public int Compare(T x, T y)
            {
                var _X = PropInfo.GetValue(x, null);
                var _Y = PropInfo.GetValue(y, null);
                if (Direction == System.ComponentModel.ListSortDirection.Ascending)
                    return System.Collections.Comparer.Default.Compare(_X, _Y);
                else
                    return System.Collections.Comparer.Default.Compare(_Y, _X);
            }
        }
    }
}
